package com.nick.gateway.service.impl;

import com.nick.gateway.service.DynamicRouteService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

/**
 * @ClassName: DynamicRouteServiceImpl
 * @Descpriction: 动态路由实现类
 * @author: zhangchao
 * @date: 2020/4/30 13:45
 * @version: 1.0
 */
@Service
@Slf4j
public class DynamicRouteServiceImpl implements DynamicRouteService {
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }


    /**
     * 增加路由
     */
    @Override
    public void addRoute(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     * 更新路由
     */
    @Override
    public void updateRoute(RouteDefinition definition) {
        try {
            deleteRoute(definition.getId());
        } catch (Exception e) {
            throw new RuntimeException("更新路由失败,路由ID:{}" + definition.getId());
        }
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            throw new RuntimeException("更新路由失败,路由ID:{}" + definition.getId());
        }
    }

    /**
     * 删除路由
     */
    @Override
    public Mono<ResponseEntity<Object>> deleteRoute(String id) {
        return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> {
            return Mono.just(ResponseEntity.ok().build());
        })).onErrorResume((t) -> {
            return t instanceof NotFoundException;
        }, (t) -> {
            return Mono.just(ResponseEntity.notFound().build());
        });
    }
}
